<script setup lang="ts">
import {
  Enums,
  RenderingEngine,
  Types,
  volumeLoader,
  utilities, setVolumesForViewports, imageLoader, CONSTANTS
} from '@cornerstonejs/core'
import { adaptersSEG } from '@cornerstonejs/adapters'
import { metaData } from '@cornerstonejs/core'
import { onMounted, reactive, ref, watchEffect } from 'vue'
import * as cornerstoneTools from '@cornerstonejs/tools'
import { initDemo, createImageIdsAndCacheMetaData } from '@/helpers'
import {
  StackScrollMouseWheelTool,
  ToolGroupManager,
  SegmentationDisplayTool,
  ZoomTool,
  TrackballRotateTool
} from '@cornerstonejs/tools'

import Controls from '@/components/Controls.vue'
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader'

const { wadors, wadouri } = cornerstoneDICOMImageLoader


const idPrefix = 'load-segment-volume'
const uuid = utilities.uuidv4()
let renderingEngineId = `${idPrefix}-renderingEngineId-${uuid}`
let volumeId = `${idPrefix}-volumeId-${uuid}`
const viewportId1 = `${idPrefix}-viewportId-${uuid}-1`
const viewportId2 = `${idPrefix}-viewportId-${uuid}-2`
const viewportId3 = `${idPrefix}-viewportId-${uuid}-3`
const viewportId4 = `${idPrefix}-viewportId-${uuid}-4`
const toolGroupId = `${idPrefix}-toolGroupId-${uuid}`
const toolGroup3dId = `${idPrefix}-toolGroupId-${uuid}-3d`
const segmentationId = 'segmentation-image-volume:' + uuid

const { ViewportType } = Enums

// const { cornerVal, updateCornerVal } = useFourCorner([viewportId])
let renderingEngine
let imageIds
let volume
let toolGroup
let toolGroup3d
const axRef = ref(null)
const sagRef = ref(null)
const corRef = ref(null)
const surfaceContainerRef = ref(null)
const {
  segmentation,
  Enums: csToolsEnums
} = cornerstoneTools

const {MouseBindings } = csToolsEnums

async function getImageIds() {
  const params = {
    StudyInstanceUID:
      '1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463',
    SeriesInstanceUID:
      '1.3.6.1.4.1.14519.5.2.1.7009.2403.226151125820845824875394858561',
    wadoRsRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb'
  }
  imageIds = await createImageIdsAndCacheMetaData(params)
}

async function addSegmentationsToState() {
  const segmentationVolume = await volumeLoader.createAndCacheDerivedSegmentationVolume(volumeId, {
    volumeId: segmentationId
  })
  segmentation.addSegmentations([
    {
      segmentationId: segmentationId,
      representation: {
        type: csToolsEnums.SegmentationRepresentations.Labelmap,
        data: {
          volumeId: segmentationId
        }
      }
    }
  ])
  // Add the segmentation representation to the toolgroup
  await segmentation.addSegmentationRepresentations(toolGroupId, [
    {
      segmentationId,
      type: csToolsEnums.SegmentationRepresentations.Labelmap
    }
  ])

  //
  return segmentationVolume
}


const initTools = () => {
  toolGroup = ToolGroupManager.createToolGroup(toolGroupId)
  // toolGroup3d = ToolGroupManager.createToolGroup(toolGroup3dId)

  toolGroup.addTool(StackScrollMouseWheelTool.toolName)
  toolGroup.addTool(SegmentationDisplayTool.toolName)
  toolGroup.addTool(ZoomTool.toolName)
  toolGroup.addTool(TrackballRotateTool.toolName)


  toolGroup.setToolEnabled(SegmentationDisplayTool.toolName)
  toolGroup.setToolActive(StackScrollMouseWheelTool.toolName)

  toolGroup.setToolActive(TrackballRotateTool.toolName, {
    bindings: [
      {
        mouseButton: MouseBindings.Primary
      }
    ]
  })

  toolGroup.setToolActive(ZoomTool.toolName, {
    bindings: [
      {
        mouseButton: MouseBindings.Secondary // Right Click
      }
    ]
  })

  // toolGroup3d.addTool(ZoomTool.toolName)
  // toolGroup3d.addTool(TrackballRotateTool.toolName, {
  //   configuration: { volumeId }
  // })
  //
  //
  //
  // toolGroup3d.setToolActive(TrackballRotateTool.toolName, {
  //   bindings: [
  //     {
  //       mouseButton: MouseBindings.Primary
  //     }
  //   ]
  // })
  //
  // toolGroup3d.setToolActive(ZoomTool.toolName, {
  //   bindings: [
  //     {
  //       mouseButton: MouseBindings.Secondary // Right Click
  //     }
  //   ]
  // })
}

const initRender = async () => {
  renderingEngine = new RenderingEngine(renderingEngineId)
  const viewportInputArray: any = [
    {
      viewportId: viewportId1,
      type: ViewportType.ORTHOGRAPHIC,
      element: axRef.value![0],
      defaultOptions: {
        orientation: Enums.OrientationAxis.AXIAL,
        background: <Types.Point3>[0, 0, 0]
      }
    },
    {
      viewportId: viewportId2,
      type: ViewportType.ORTHOGRAPHIC,
      element: sagRef.value![0],
      defaultOptions: {
        orientation: Enums.OrientationAxis.SAGITTAL,
        background: <Types.Point3>[0, 0, 0]
      }
    },
    {
      viewportId: viewportId3,
      type: ViewportType.ORTHOGRAPHIC,
      element: corRef.value![0],
      defaultOptions: {
        orientation: Enums.OrientationAxis.CORONAL,
        background: <Types.Point3>[0, 0, 0]
      }
    },
    {
      viewportId: viewportId4,
      type: ViewportType.VOLUME_3D,
      element: surfaceContainerRef.value![0],
      defaultOptions: {
        background: <Types.Point3>[0.2, 0, 0.2]
      }
    }
  ]
  renderingEngine.setViewports(viewportInputArray)


  toolGroup.addViewport(viewportId1, renderingEngineId)
  toolGroup.addViewport(viewportId2, renderingEngineId)
  toolGroup.addViewport(viewportId3, renderingEngineId)
  toolGroup.addViewport(viewportId4, renderingEngineId)

  // toolGroup3d.addViewport(viewportId4, renderingEngineId)

  volume.load()
  await setVolumesForViewports(
    renderingEngine,
    [{ volumeId }],
    [viewportId1, viewportId2, viewportId3, viewportId4]
  )
  const viewport3d = renderingEngine.getViewport(viewportId4)
  const volumeActor = viewport3d.getDefaultActor().actor as Types.VolumeActor
  // 这里和体绘制采用的参数好像一样。
  utilities.applyPreset(
    volumeActor,
    CONSTANTS.VIEWPORT_PRESETS.find(
      (preset) => preset.name === 'CT-Bone'
    ) as any
  )
  const renderer = viewport3d.getRenderer()
  renderer.getActiveCamera().elevation(-70)
  viewport3d.setCamera({ parallelScale: 600 })
  renderingEngine.renderViewports([viewportId1, viewportId2, viewportId3, viewportId4])
}

async function createVolume() {
  volume = await volumeLoader.createAndCacheVolume(volumeId, {
    imageIds
  })
}

onMounted(async () => {
  await initDemo()
  initTools()
  // listenEvent()
  await getImageIds()
  await createVolume()
  // await addSegmentationsToState()
  await initRender()
})

// const listenEvent = () => {
//   (renderContainerRef.value as any).addEventListener(VOLUME_NEW_IMAGE, ((
//     evt: Types.EventTypes.VolumeNewImageEvent
//   ) => {
//     updateCornerVal(viewportId, {
//       [FOUR_CORNER_SHOW_NAME.INDEX]: evt.detail.imageIndex,
//       [FOUR_CORNER_SHOW_NAME.TOTAL]: evt.detail.numberOfSlices
//     })
//   }) as EventListener)
// }

const labelSetting = reactive({
  thickness: 10,
  outlineOpacity: 1,
  fillOpacity: 1
})

// watchEffect(() => {
//   segmentation.config.setToolGroupSpecificConfig(toolGroupId, {
//     renderInactiveSegmentations: true,
//     representations: {
//       [SegmentationRepresentations.Labelmap]: {
//         renderFill: true,
//         renderOutline: true,
//         outlineWidthActive: labelSetting.thickness,
//         fillAlpha: labelSetting.fillOpacity,
//         outlineOpacity: labelSetting.outlineOpacity
//       }
//     }
//   })
// })
const selectRef = ref(null)
const handleFileSelect = async (evt) => {
  const files = evt.target.files

  for (let i = 0; i < files.length; i++) {
    const file = files[i]

    await readSegmentation(file)
  }
}

async function readSegmentation(file) {
  const imageId = wadouri.fileManager.add(file)

  const image = await imageLoader.loadAndCacheImage(imageId)
  if (!image) {
    return
  }
  const instance = metaData.get('instance', imageId)

  if (instance.Modality !== 'SEG') {
    console.error('This is not segmentation')
    return
  }
  const arrayBuffer = image.data.byteArray.buffer
  await loadSegmentation(arrayBuffer)
}

const loadSegmentation = async (arrayBuffer) => {
  const generateToolState =
    await adaptersSEG.Cornerstone3D.Segmentation.generateToolState(
      imageIds,
      arrayBuffer,
      metaData
    )

  const derivedVolume = await addSegmentationsToState()
  //
  const derivedVolumeScalarData = derivedVolume.getScalarData()
  //
  derivedVolumeScalarData.set(
    new Uint8Array(generateToolState.labelmapBufferArray[0])
  )
}
const views = [
  {
    'ref': axRef,
    'class': 'lt',
    'viewportId': viewportId1
  },
  {
    'ref': sagRef,
    'class': 'lb',
    'viewportId': viewportId2
  },
  {
    'ref': corRef,
    'class': 'rt',
    'viewportId': viewportId3
  },
  {
    'ref': surfaceContainerRef,
    'class': 'rb',
    'viewportId': viewportId4
  }
]
</script>

<template>
  <input type="file" ref="selectRef" multiple accept=".dcm" @change="handleFileSelect">
  <div class="w-full h-[500px] flex">
    <div class="flex-1 ml-auto mr-auto h-[500px] grid grid-cols-2 grid-rows-2 border-2 border-amber-200">
      <template v-for="view in views" :key="view.class">
        <div
          :class="[view.class,  'border-transparent']"
          :ref="view.ref">
        </div>
      </template>
    </div>

    <div class="w-[200px]">
      <controls
        v-model:thickness="labelSetting.thickness"
        v-model:outlineOpacity="labelSetting.outlineOpacity"
        v-model:fillOpacity="labelSetting.fillOpacity"
      />
    </div>
  </div>

</template>

<style scoped>

</style>
